Mở đầu

Đôi khi việc xử lý độ cao cột thò thụt không chính xác cũng là một vấn đề nan giải.việc thực hiện giải pháp bên dưới sẽ giúp công việc của bạn đỡ bần hơn.

Cách thực hiện

import sys
pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)
import math
import random as rnd
import clr
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Structure import *
clr.AddReference('RevitAPIUI')
from Autodesk.Revit.UI import *
clr.AddReference('System')
import System
from System.Collections.Generic import *
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.ImportExtensions(Revit.Elements)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
def flatten(x):
result = []
for el in x:
if hasattr(el, "__iter__") and not isinstance(el, basestring):
result.extend(flatten(el))
else:
result.append(el)
return result
def GetLevelAbove(level, tolerance):
sorted_lvls = sorted(FilteredElementCollector(doc).OfClass(Level).ToElements(), key=lambda x: x.Elevation)
sorted_nams = [ i.Name for i in sorted_lvls ]
index = sorted_nams.index(level.Name)
if index + 1 >= len(sorted_lvls): return level
result = sorted_lvls[index + 1]
if result.Elevation - level.Elevation < tolerance:
return GetLevelAbove(result, tolerance)
return result
def GetLevelByElevation(value, tolerance):
seach_val = round(value// (tolerance/2)) * (tolerance/2)
provider = ParameterValueProvider(ElementId(BuiltInParameter.LEVEL_ELEV))
filterrule = FilterDoubleRule(provider, FilterNumericEquals(), seach_val, tolerance)
collector = FilteredElementCollector(DocumentManager.Instance.CurrentDBDocument).OfClass(Level)
level = collector.WherePasses(ElementParameterFilter(filterrule)).FirstElement()
if level == None:
tolerance = tolerance + (150 / 304.8)
try: return GetLevelByElevation(value, tolerance)
except: pass
return level
def GetSortedLevels():
return sorted(FilteredElementCollector(doc).OfClass(Level).ToElements(), key=lambda x: x.Elevation)
def GetCollumns():
collumns = []
for level in GetSortedLevels():
levelfilter = ElementLevelFilter(level.Id)
collector = FilteredElementCollector(doc).WherePasses(levelfilter).WhereElementIsNotElementType()
elements = collector.OfCategory(BuiltInCategory.OST_StructuralColumns).ToElements()
collumns.extend(elements)
return collumns
def GetWallsByWidht(value, evaluator):
result = []
for level in GetSortedLevels():
level_filter = ElementLevelFilter(level.Id)
provider = ParameterValueProvider(ElementId(BuiltInParameter.WALL_ATTR_WIDTH_PARAM))
filterrule = FilterDoubleRule(provider, evaluator, value, 0.05)
prm_filter = ElementParameterFilter(filterrule)
collector = FilteredElementCollector(doc).WherePasses(level_filter).OfClass(Wall)
walls = collector.WherePasses(prm_filter).WhereElementIsNotElementType().ToElements()
result.extend(walls)
return result
def GetElementSolid(item):
geo_elem = item.get_Geometry(Autodesk.Revit.DB.Options()).GetTransformed(Transform.Identity)
solids = [geo for geo in geo_elem if 'Solid' in geo.ToString() and geo.Volume > 0 ]
util = BooleanOperationsUtils
type = BooleanOperationsType.Union
for i, solid in enumerate(solids):
if i == 0: usolid = solid
elif i != 0: usolid = util.ExecuteBooleanOperation(usolid, solid[i], type)
else: usolid = solid
return usolid
def GetCentroid(item):
solid = GetElementSolid(item)
centroid = solid.ComputeCentroid()
return centroid
def GetRayIntersection(point, filter_class, direction):
point = XYZ(point.X, point.Y, point.Z)
view = FilteredElementCollector(doc).OfClass(View3D).ToElements()
view = [v for v in view if v.IsTemplate != True][0]
filter = ElementClassFilter(filter_class)
refIntersector = ReferenceIntersector(filter, FindReferenceTarget.All, view)
refIntersector.FindReferencesInRevitLinks = True
refwc = refIntersector.FindNearest(point, direction)
if refwc:
reference = refwc.GetReference()
represent = reference.ConvertToStableRepresentation(doc)
element = doc.GetElement(represent)
intersection = reference.GlobalPoint
return intersection.Z
def SetCorrectCollumnTopLevel(item, recursion):
tolerance = 1800/304.8
base_level_prm = item.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_PARAM)
top_level_prm = item.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_PARAM)
base_level = doc.GetElement(base_level_prm.AsElementId())
top_level = doc.GetElement(top_level_prm.AsElementId())
base_elev = base_level.Elevation
center = GetCentroid(item)
point = XYZ(center.X, center.Y, base_elev + (base_elev - center.Z)*0.5)
height = GetRayIntersection(point, Floor, XYZ(0, 0, 1))
if not height or height <= base_elev and recursion != True:
return SetCorrectCollumnTopLevel(item, True)
elif height and height > base_elev:
new_top_level = GetLevelByElevation(height, tolerance/3)
if top_level.Id != new_top_level.Id:
return top_level_prm.Set(new_top_level.Id)
else:
new_top_level = GetLevelAbove(base_level, tolerance)
if top_level.Id != new_top_level.Id:
return top_level_prm.Set(new_top_level.Id)
def SetCorrectCollumnTopOffset(item):
if not item: return
point = GetCentroid(item)
height = GetRayIntersection(point, Floor, XYZ(0, 0, 1))
if not height: return
top_offset_prm = item.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_OFFSET_PARAM)
top_level_prm = item.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_PARAM)
top_level = doc.GetElement(top_level_prm.AsElementId())
top_elev = top_level.Elevation
top_offset = height - top_elev
return top_offset_prm.Set(top_offset)
def DeleteDuplicate(item):
solid = GetElementSolid(item)
solidfilter = ElementIntersectsSolidFilter(solid)
collector = FilteredElementCollector(doc).WhereElementIsNotElementType().WherePasses(solidfilter)
intersect = collector.OfCategory(BuiltInCategory.OST_StructuralColumns).FirstElement()
centroid = GetCentroid(item)
if intersect and GetCentroid(intersect).AlmostEqual(centroid):
return doc.Delete(item.Id)
def GetAverageValue(values):
result = [float(i) for i in flatten(values) if i]
if len(result) == 1: return result[0]
if len(result) >= 2:
maxfilter = (max(result) + sum(result) / len(result) + 0.0005) * 0.5
minfilter = (min(result) + sum(result) / len(result) - 0.0005) * 0.5
result = [i for i in result if i <= maxfilter and i >= minfilter]
try: return sum(result) / len(result)
except: pass
def SetWallHeight(wall):
try: curve = wall.Location.Curve
except: return False
tollerance = 1800 / 304.8
level = wall.Document.GetElement(wall.LevelId)
above_level = GetLevelAbove(level, tollerance)
if above_level == None or level.Id == above_level.Id: return False
samples = int(round(curve.Length / tollerance) + 1)
if samples > 10 or samples < 3: samples = 5
points = [curve.Evaluate(round(0.5 / samples + float(i) / samples, 3), True) for i in range(samples)]
values = [GetRayIntersection(p, Floor, XYZ(0, 0, 1)) for p in points]
height = GetAverageValue(values)
if height:
calc_height = height - level.Elevation
wall_height = wall.get_Parameter(BuiltInParameter.WALL_USER_HEIGHT_PARAM).AsDouble()
if calc_height and calc_height >= tollerance and wall_height > tollerance and wall_height != calc_height:
wall.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE).Set(ElementId.InvalidElementId)
wall.get_Parameter(BuiltInParameter.WALL_USER_HEIGHT_PARAM).Set(calc_height)
return True
def CreateModelCurve(startpoint, endpoint):
geomplane = Plane.CreateByNormalAndOrigin(XYZ.BasisX, startpoint)
sketch = SketchPlane.Create(uidoc.Document, geomplane)
uidoc.Document.ActiveView.SketchPlane = sketch
uidoc.Document.ActiveView.ShowActiveWorkPlane()
line = Line.CreateBound(startpoint, endpoint)
modelcurve = doc.Create.NewModelCurve(line, sketch)
return modelcurve
# Element.Name.GetValue(item)
###################################################################################################
items = GetCollumns()
TransactionManager.Instance.EnsureInTransaction(doc)
result = [SetCorrectCollumnTopLevel(item, False) for item in items if item]
doc.Regenerate()
TransactionManager.Instance.TransactionTaskDone()
###################################################################################################
items = GetWallsByWidht((100/304.8), FilterNumericGreaterOrEqual())
TransactionManager.Instance.EnsureInTransaction(doc)
result = [SetWallHeight(item) for item in items if item]
doc.Regenerate()
TransactionManager.Instance.TransactionTaskDone()
###################################################################################################
items = GetCollumns()
TransactionManager.Instance.EnsureInTransaction(doc)
result = [SetCorrectCollumnTopOffset(item) for item in items if item]
doc.Regenerate()
TransactionManager.Instance.TransactionTaskDone()
OUT = result

Tham khảo

DynamoChatDev